package com.summer.filesync.network;

import com.summer.filesync.config.ConfigManager;
import com.summer.filesync.config.SystemConfig;
import com.summer.filesync.model.Message;
import com.summer.filesync.util.Logger;
import java.util.Set;

/** 心跳服务 定期发送心跳包检测节点连接状态 */
public class HeartbeatService implements Runnable {

  private static final Logger logger = Logger.getLogger(HeartbeatService.class);

  private NetworkManager networkManager;
  private long heartbeatInterval;
  private boolean running = true;

  public HeartbeatService(NetworkManager networkManager) {
    this.networkManager = networkManager;

    ConfigManager config = ConfigManager.getInstance();
    this.heartbeatInterval =
        config.getLongProperty(
            SystemConfig.HEARTBEAT_INTERVAL, SystemConfig.Defaults.HEARTBEAT_INTERVAL);

    logger.info("HeartbeatService initialized with interval: " + heartbeatInterval + "ms");
  }

  @Override
  public void run() {
    logger.info("HeartbeatService started");

    while (running && networkManager.isRunning()) {
      try {
        // 等待心跳间隔
        Thread.sleep(heartbeatInterval);

        if (!running) {
          break;
        }

        // 发送心跳到所有连接的节点
        sendHeartbeats();

        // 检查节点连接状态
        checkNodeConnections();

      } catch (InterruptedException e) {
        logger.info("HeartbeatService interrupted");
        Thread.currentThread().interrupt();
        break;
      } catch (Exception e) {
        logger.error("Error in heartbeat service", e);
      }
    }

    logger.info("HeartbeatService stopped");
  }

  /** 发送心跳到所有连接的节点 */
  private void sendHeartbeats() {
    Set<String> onlineNodes = networkManager.getOnlineNodes();

    if (onlineNodes.isEmpty()) {
      logger.debug("No nodes to send heartbeat to");
      return;
    }

    logger.debug("Sending heartbeats to " + onlineNodes.size() + " nodes");

    Message heartbeatMessage =
        new Message(
            Message.MessageType.HEARTBEAT,
            networkManager.getLocalNodeId(),
            null, // 广播
            "PING");

    for (String nodeId : onlineNodes) {
      try {
        heartbeatMessage.setTargetNodeId(nodeId);
        boolean sent = networkManager.sendMessage(nodeId, heartbeatMessage);

        if (!sent) {
          logger.warn("Failed to send heartbeat to node: " + nodeId);
        }

      } catch (Exception e) {
        logger.error("Error sending heartbeat to node: " + nodeId, e);
      }
    }
  }

  /** 检查节点连接状态 */
  private void checkNodeConnections() {
    Set<String> onlineNodes = networkManager.getOnlineNodes();

    // 这里可以添加更详细的连接健康检查
    // 比如检查连接是否超时、是否响应等

    for (String nodeId : onlineNodes) {
      try {
        // 可以在这里添加特定的连接检查逻辑
        // 例如：检查最后心跳时间、ping测试等

      } catch (Exception e) {
        logger.error("Error checking connection for node: " + nodeId, e);
      }
    }
  }

  /** 处理心跳响应 */
  public void handleHeartbeatResponse(String nodeId, Message response) {
    if (response.getType() == Message.MessageType.HEARTBEAT) {
      String payload = (String) response.getPayload();
      if ("PONG".equals(payload)) {
        logger.debug("Received heartbeat response from: " + nodeId);
        // 心跳响应正常，连接健康
      } else {
        logger.warn("Invalid heartbeat response from: " + nodeId + ", payload: " + payload);
      }
    }
  }

  /** 设置心跳间隔 */
  public void setHeartbeatInterval(long interval) {
    if (interval > 0) {
      this.heartbeatInterval = interval;
      logger.info("Heartbeat interval updated to: " + interval + "ms");
    } else {
      logger.warn("Invalid heartbeat interval: " + interval);
    }
  }

  /** 获取心跳间隔 */
  public long getHeartbeatInterval() {
    return heartbeatInterval;
  }

  /** 停止心跳服务 */
  public void stop() {
    running = false;
    logger.info("HeartbeatService stop requested");
  }

  /** 检查是否正在运行 */
  public boolean isRunning() {
    return running;
  }

  /** 获取服务状态信息 */
  public String getStatusInfo() {
    return "HeartbeatService{"
        + "running="
        + running
        + ", interval="
        + heartbeatInterval
        + ", connectedNodes="
        + networkManager.getConnectedNodeCount()
        + '}';
  }
}
